package com.hczt.xhminiapp.appapi.weixin.service;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.hczt.xhminiapp.appapi.weixin.dto.WxErrRtn;
import com.hczt.xhminiapp.appapi.weixin.dto.WxOpenIDInfo;
import com.hczt.xhminiapp.appapi.weixin.dto.WxProperties;
import com.hczt.xhminiapp.appapi.weixin.utils.WxErrorCodeTool;
import com.hczt.xhminiapp.appapi.weixin.utils.WxUserInfoUtil;
import com.hczt.xhminiapp.common.bean.CodeMsg;
import com.hczt.xhminiapp.common.bean.Constants;
import com.hczt.xhminiapp.common.bean.RtnResult;
import com.hczt.xhminiapp.common.utils.JacksonUtil;
import com.hczt.xhminiapp.db.entity.Doctor;
import com.hczt.xhminiapp.db.entity.Patient;
import com.hczt.xhminiapp.db.repository.DoctorRepository;
import com.hczt.xhminiapp.db.repository.PatientRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Date;

/**
 * @author 红创-马海强
 * @date 2019-03-07 17:05
 * @description 微信业务处理类
 */
@Slf4j
@Service
public class WxService {
    /**
     * 微信属性
     */
    @Autowired
    private WxProperties wxProperties;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DoctorRepository doctorRepository;

    @Autowired
    private PatientRepository patientRepository;

    /**
     * 根据code获取用户信息
     * 1.通过code换取页面授权sccess_token
     * 2.根据access_token与openid获取用户信息
     * 3.用户信息保存或更新到数据库
     * 4.组装返回结果
     *
     * @param code 获取为用户信息的code
     * @return
     * @throws Exception
     */
    public RtnResult<Object> getUserInfoByCode(String role, String code) throws Exception {
        //header里的角色必传，如果没有直接返回错误
        if(StringUtils.isBlank(role) ||
                !Constants.DOCTOR.equalsIgnoreCase(role) ||
                !Constants.PATIENT.equalsIgnoreCase(role)) {
            return RtnResult.error(CodeMsg.ROLE_ERROR);
        }
        String appid;
        String secret;
        if(Constants.DOCTOR.equals(role)) {
            appid = wxProperties.getDoctorAppid();
            secret = wxProperties.getDoctorSecret();
        } else {
            appid = wxProperties.getPatientAppid();
            secret = wxProperties.getPatientSecret();
        }
        //1.通过code换取网页授权access_token
        String tokenUrl = WxUserInfoUtil.getWebAccess(appid, secret, code);
        log.info("通过code换取网页授权access_token请求url为【{}】", tokenUrl);
        ResponseEntity<String> accessTokenResponse = restTemplate.getForEntity(tokenUrl, String.class);
        int accessTokenStatusCodeValue = accessTokenResponse.getStatusCodeValue();
        //返回的状态不是200
        if (HttpStatus.OK.value() != accessTokenStatusCodeValue) {
            log.error("通过code换取网页授权access_token请求失败，状态码为【{}】,返回消息体为【{}】", accessTokenStatusCodeValue, accessTokenResponse.getBody());
            return RtnResult.error(CodeMsg.LOGIN_WX_ERROR);
        }
        log.info("通过code换取网页access_token请求成功，返回值为【{}】", accessTokenResponse.getBody());
        // 判断返回值中是否存在errcode，如果存在，表示失败
        if (JacksonUtil.hasKey(accessTokenResponse.getBody(), "errcode")) {
            WxErrRtn wxErrRtn = getWxErr(accessTokenResponse.getBody());
            log.error("获取access_token，消息体错误, 状态码为【{}】,返回消息体为【{}】", Integer.parseInt(wxErrRtn.getErrcode()), wxErrRtn.getErrmsg());
            return RtnResult.error(CodeMsg.LOGIN_WX_ERROR);
        }
        //2.将返回结果转换为WxAccessTokenInfo对象
        WxOpenIDInfo wxOpenIDInfo = JacksonUtil.json2Pojo(accessTokenResponse.getBody(), WxOpenIDInfo.class);
        // 将微信用户信息保存到redis中
        //redisService.set(WxRedisKey.getUserByOpenId,wxUserInfo.getOpenid(),user);
        if(Constants.DOCTOR.equalsIgnoreCase(role)) {
            Doctor doctor = doctorRepository.findByOpenidAndDeletedIsFalse(wxOpenIDInfo.getOpenid());
            if(null == doctor) {
                doctor = new Doctor();
                doctor.setCreateTime(new Date());
                doctor.setOpenid(wxOpenIDInfo.getOpenid());
                doctor.setDeleted(false);
                doctor.setUnionid(wxOpenIDInfo.getUnionid());
                doctorRepository.save(doctor);
            }
        } else if(Constants.PATIENT.equalsIgnoreCase(role)) {
            Patient patient = patientRepository.findByOpenidAndDeletedIsFalse(wxOpenIDInfo.getOpenid());
            if(null == patient) {
                patient = new Patient();
                patient.setOpenid(wxOpenIDInfo.getOpenid());
                patient.setDeleted(false);
                patient.setUnionid(wxOpenIDInfo.getUnionid());
                patient.setCreateTime(new Date());
                patientRepository.save(patient);
            }
        }

        return RtnResult.success(wxOpenIDInfo);
    }

    /**
     * 获取微信错误信息
     *
     * @param jsonStr
     * @return
     * @throws JsonParseException
     * @throws JsonMappingException
     * @throws IOException
     */
    private WxErrRtn getWxErr(String jsonStr) throws JsonParseException, JsonMappingException, IOException {
        WxErrRtn wxErrRtn = JacksonUtil.json2Pojo(jsonStr, WxErrRtn.class);
        // 错误信息是否在微信错误列表中
        String errMsg = WxErrorCodeTool.get(wxErrRtn.getErrcode());
        if (StringUtils.isNotBlank(errMsg)) {
            wxErrRtn.setErrmsg(errMsg);
        }
        return wxErrRtn;
    }
}
